#include <nemesis.functions.h>
#include <nemesis.Logger.h>

#include <nemesis.app.functions.h>
#include <nemesis.app.Application.h>

#include <nemesis.io.functions.h>

#include <nemesis.dbms.Database.h>
#include <nemesis.dbms.Statement.h>

#include <nemesis.dbms.oracle.Database.h>

#include <nemesis.dbos.Repository.h>

#include <dbos_demo.oodb.Table01.h>
#include <dbos_demo.oodb.Table02.h>
#include <dbos_demo.oodb.Table03.h>

using namespace std;
using namespace nemesis;
using namespace dbos_demo;

oodb::Table01::Loader* oodb::Table01::st_loader = NULL;

dbos_prepare_object (oodb::Table01);

void oodb::Table01::setup (dbms::Database& database, dbos::Repository& repository)
   throw (RuntimeException)
{
   st_loader = new Table01::Loader (database);

   Table01::setStorageArea (
      repository.createStorageArea (                                                  
         Table01::getStorageAreaId (), Table01::getStorageAreaName (), Table01::getMaxSize (),
         Table01::allocator, 2, dbos::StorageArea::AccessMode::ReadWrite
      )
   );
}

oodb::Table01* oodb::Table01::instanciate (dbms::Connection& connection, const int id)
   throw (RuntimeException)
{
   if (st_loader == NULL)
      throw RuntimeException ("smart::oodb::Table01::setup no ha sido invocado", FILE_LOCATION);

   Table01* result = NULL;

   try {
      Guard guard (st_loader, "smart::oodb::Table01::Loader");
      result = dbos::ObjectFacade <Table01>::instanciate (connection, st_loader->setKey (id));
   }
   catch (dbms::DatabaseException& edb) {
      throw RuntimeException (edb);
   }

   return result;
}

void oodb::Table01::initialize (dbos::Loader& loader)
   throw (RuntimeException, dbms::DatabaseException)
{
   Table01::Loader& dbLoader = static_cast <Table01::Loader&> (loader);

   dbms::Connection& connection = loader.getConnection ();

   a_id = dbLoader.getId ();

   LOGINFORMATION (
      string msg ("dbos_demo::oodb::Table01::initialize | Id: ");
      msg += nemesis::functions::asString (a_id);
      Logger::information (msg, FILE_LOCATION);
   );

   a_table02 = Table02::instanciate (connection, dbLoader.getTable02 ());
   a_table03 = Table03::instanciate (connection, dbLoader.getTable03 ());
}

void oodb::Table01::destroy ()
   throw ()
{
   LOGINFORMATION (
      string msg ("dbos_demo::oodb::Table01::destroy | Id: ");
      msg += nemesis::functions::asString (a_id);
      Logger::information (msg, FILE_LOCATION);
   );

   Table02::release (a_table02);
   Table03::release (a_table03);
}

string oodb::Table01::asString () const
   throw ()
{
   std::string result ("smart::oodb::Table01 { Id: ");
   result += nemesis::functions::asString (a_id);
   result += " | ";
   result += a_table02->asString ();
   result += " | ";
   result += a_table03->asString ();
   return result += " }";
}

//--------------------------------------------------------------------------------
// Definicin del cargador
//--------------------------------------------------------------------------------
dbms::Statement* oodb::Table01::Loader::initialize (dbms::Database& database)
   throw (RuntimeException)
{
   dbms::Statement* statement = database.createStatement (
      "table01", "select ref02,ref03 from nemesis_db_table01 where key=:id"
   );
   statement->bindInput ("id", a_id);
   statement->bindOutput ("ref02", a_ref02);
   statement->bindOutput ("ref03", a_ref03);
   return statement;
}

string oodb::Table01::Loader::asString () const
   throw ()
{
   std::string result ("smart::oodb::Loader::Table01 { Id: ");
   result += nemesis::functions::asString (a_id);
   return result += " }";
}

